package com.ztesoft.web.ssh;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ztesoft.framework.log.ZTEsoftLogManager;
import com.ztesoft.web.common.Util;
import org.apache.log4j.Logger;

import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import com.ztesoft.web.common.vo.HostInfoPOJO;

/**
 * SSH2协议获取  标准输出、标准错误
* @ClassName: SSH2Client 
* @Description: 
* @author Qiu.WeiCheng
* @date 2016-5-18 下午3:29:01 
*  
* @version   V1.0
 */
public class SSH2Client {
	
	private String ip;
	
	private String user;
	
	private String passWord;
	
	private int port = 22;

	private String charset = Charset.defaultCharset().toString();
	
	private Connection conn = null;
	
	private InputStream stdOut = null;
	
	private InputStream stdErr = null;
	

    private static final int TIME_OUT = 1000 * 60;//单位毫秒，设置60s

	private static final ZTEsoftLogManager logger = ZTEsoftLogManager.getLogger(SSH2Client.class);

	public SSH2Client(String ip, String user, String passWord) {
		this.ip = ip;
		this.user = user;
		this.passWord = passWord;
	}
	
	/**
	 * 包含端口传输 add by lin.wb
	 * @param hostInfoPOJO
	 */
	public SSH2Client(HostInfoPOJO hostInfoPOJO) {
		this.ip = hostInfoPOJO.getHostIp();
		this.user = hostInfoPOJO.getUserName();
		this.passWord = hostInfoPOJO.getPwd();
		this.port = hostInfoPOJO.getPort();
	}
	
	/**
	 * ssh2登录
	 * @return
	 * @throws IOException
	 */
	public boolean ssh2Login() throws IOException {
        conn = new Connection(ip, port);
        conn.connect();
        return conn.authenticateWithPassword(user, passWord);
    }
	
	/**
	 * 流转为字符串
	 * @param in
	 * @param charset
	 * @return
	 * @throws IOException
	 */
	public String processStream(InputStream in, String charset) throws IOException {
        StringBuffer sb = new StringBuffer();
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
	    byte[] buffer = new byte[1024];  
	    int len = -1;  
	    while ((len = in.read(buffer)) != -1) {  
	        outSteam.write(buffer, 0, len);  
	    }  
	    outSteam.close();  
	    in.close(); 
	    Pattern p = Pattern.compile("\t|\r|\n");
        Matcher m = p.matcher(sb.append(new String(outSteam.toByteArray(), charset)).toString());
		String temp = m.replaceAll(",");//对换行做替换
        return temp;
    }
	
	/**
	 * shell执行结果
	 * @param loginFalg
	 * @param cmds
	 * @return
	 * @throws IOException
	 */
	public Map<String, Object> execNormalCommand(boolean loginFalg,String cmds) {
		Map<String, Object> map = new HashMap<String, Object>();
		Session session = null;
		String outStr = null;
        String outErr = null;
        int ret = -1;
        if (loginFalg) {
			try {
				session = conn.openSession();
				session.execCommand(cmds);
				stdOut = new StreamGobbler(session.getStdout());
				outStr = processStream(stdOut, charset);
				if(!"".equals(outStr.trim())){
					map.put("outStr", outStr);//标准输出
				}
				stdErr = new StreamGobbler(session.getStderr());
				outErr = processStream(stdErr, charset);
				if(!"".equals(outErr.trim())){
					map.put("outErr", outErr);//标准错误
				}
//	            session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
				session.waitForCondition(ChannelCondition.EXIT_STATUS, 50);
				ret = session.getExitStatus();
				map.put("status", ret);//命令执行状态【0－成功； 非0－失败】
			} catch (Exception e) {
				map.put("status", -1);//命令执行状态【0－成功； 非0－失败】
				logger.error("[error] :"+cmds,e);
			} finally {
				if (session != null) {
					session.close();
				}
			}
		}else{
        	map.put("status", ret);//命令执行状态【0－成功； 非0－失败】
        	logger.error("[error] ssh login fail,ip:"+ip+",user:"+user+",password:"+passWord);
        }
		return map;
	}
	
	/**
	 * 关闭连接
	 */
	public void closeConnect(){
		try {
			if (conn != null) {
	            conn.close();
	        }
			if (stdOut != null){
	            stdOut.close();
	        }
	        if (stdErr != null){
	            stdErr.close();
	        }
		} catch (Exception e) {
			logger.error("[error] error info :"+e);
		}
        
	}
}
